package com.example.demo.t2;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class T2_3<K,V> implements Iterable<K>  {

    private final Integer MAX = 3;
    private LinkedHashMap<K, V> cache = new LinkedHashMap<>();
    public void cache(K key, V value) {
        if (cache.containsKey(key)) {
            cache.remove(key);
        }
        if (cache.size() >= MAX) {
            var it = cache.keySet().iterator();
            var k = it.next();
            cache.remove(k);
        }
        cache.put(key, value);
    }

//    @Override
//    public String toString() {
//        var it = linkedHashMap.keySet().iterator();
//        String out = "leave";
//        while (it.hasNext()) {
//            var k = it.next();
//            out += " <- " + k + "(" + linkedHashMap.get(k) + ")";
//        }
//        return out;
//    }

    public V get(K key){
        if (cache.containsKey(key))
            return cache.get(key);
        return null;
    }

    @Override
    public Iterator<K> iterator() {
        var it = cache.keySet().iterator();
        return new Iterator<K>() {
            @Override
            public boolean hasNext() {
                return it.hasNext();
            }

            @Override
            public K next() {
                return it.next();
            }
        };
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        var list = new T2_3<String, Integer>();
        list.cache("A", 1);
        list.cache("B", 1);
        list.cache("C", 1);
        list.cache("A", 3);
        list.cache("D", 5);
//        System.out.println(list.toString());

        System.out.println(
        StreamSupport.stream(list.spliterator(), false)
                .map(o -> o.toString())
                .collect(Collectors.joining("<-"))
        );

        Stream.of("My", "Mine")
                .flatMap(o -> o.chars().mapToObj(oo -> (char)oo))
                .collect(Collectors.toSet())
                .forEach(System.out::println);

        var set1 = Stream.of("My", "Mine")
                .flatMap(o -> o.chars().mapToObj(oo -> (char)oo))
                .collect(Collectors.toSet())
                ;
        System.out.println(set1.stream().map(o -> o.toString()).collect(Collectors.joining("-")));
        System.out.println(set1);
        System.out.println(set1.stream().collect(Collectors.toList()));



        var res = Stream.of(1,2,3,4,5)
                .sorted()
                .skip(3)
                .map(o -> o * o)
                .reduce(Math::max)
                ;

        var random = new Random();


        var list2 = IntStream.range(0, 1_000_000)
                .map(o -> random.nextInt(1_000_000))
                .boxed()
                .collect(Collectors.toList());
        var t0 = System.currentTimeMillis();
        var res2 = list2.stream().max((a,b) -> a-b);
        System.out.println(res2.get());
        System.out.println(System.currentTimeMillis() - t0);

        t0 = System.currentTimeMillis();
        var res3 = list2.stream().parallel().max((a,b) -> a-b);
        System.out.println(res3.get());
        System.out.println(System.currentTimeMillis() - t0);

        ForkJoinPool pool = new ForkJoinPool(3);
        t0 = System.currentTimeMillis();
        var res4 = pool.submit(() -> list2.parallelStream().max((a,b) -> a-b)).get();
        System.out.println(res4.get());
        System.out.println(System.currentTimeMillis() - t0);

        var t3 = Optional.of(1)
                .map(o -> o * o)
                .map(o -> o.toString())
                ;


//                .forEach(System.out::println);

    }
}
